package dao

import (
	dom "a-common/domain"
	"a-common/utils"
	"a-system/domain/entity"
	"errors"
	"strings"
	"sync"
	"time"
)

var (
	userDaoTemp *UserDao
	userDaoOnce sync.Once
)

type UserDao struct{}

func NewSysUserDao() *UserDao {
	userDaoOnce.Do(func() {
		userDaoTemp = &UserDao{}
	})
	return userDaoTemp
}

// List 列表
func (m *UserDao) List(args *entity.UserDto, isExport bool) (dom.PageVo, error) {
	// 构建查询条件
	query := pgCli.Table(&entity.SysUser{}).Join("LEFT", "sys_dept", "sys_dept.dept_id=sys_user.dept_id").Where("1 = 1")
	if args.Username != "" {
		query.And("username = ?", args.Username)
	}
	if args.Phone != "" {
		query.And("phone = ?", args.Phone)
	}
	if args.Status != "" {
		query.And("status = ?", args.Status)
	}
	if args.Params.BeginTime != "" && args.Params.EndTime != "" {
		query.And("created_at BETWEEN ? AND ?", args.Params.BeginTime, args.Params.EndTime)
	}
	if args.PageNum != 0 && args.PageSize != 0 {
		query.Limit(args.PageSize, (args.PageNum-1)*args.PageSize)
	}
	// 查询
	var vPage dom.PageVo
	if isExport {
		var rows []entity.SysUserExportVo
		total, err := query.Asc("user_id").FindAndCount(&rows)
		if err != nil {
			return vPage, err
		}
		vPage.Rows = rows
		vPage.Total = total
	} else {
		var rows []entity.SysUserPageVo
		total, err := query.Asc("user_id").FindAndCount(&rows)
		if err != nil {
			return vPage, err
		}
		vPage.Rows = rows
		vPage.Total = total
	}
	vPage.PageNum = args.PageNum
	vPage.PageSize = args.PageSize
	return vPage, nil
}

// Get 查
func (m *UserDao) Get(id int64) (entity.SysUserPageVo, error) {
	var v entity.SysUserPageVo
	_, err := pgCli.Table(&entity.SysUser{}).ID(id).Get(&v)
	return v, err
}

// Add 增
func (m *UserDao) Add(args *entity.UserDto) error {
	session := pgCli.NewSession()
	defer session.Close()
	if err := session.Begin(); err != nil {
		return err
	}

	// 加密
	pwd, err := utils.NewCryptUtils().EnCrypt(args.Password)
	if err != nil {
		return err
	}

	var sysUser = &entity.SysUser{
		Username: args.Username,
		Nickname: args.Nickname,
		Phone:    args.Phone,
		Email:    args.Email,
		Password: pwd,
		Status:   args.Status,
		BaseStruct: dom.BaseStruct{
			CreatedBy: args.CreatedBy,
			UpdatedBy: args.CreatedBy,
			Remark:    args.Remark,
		},
	}
	if _, err := pgCli.Insert(sysUser); err != nil {
		return err
	}
	if sysUser.UserId == 0 {
		return errors.New("新增失败")
	}

	// 新增用户与角色管理
	var userRoles []entity.SysUserRole
	for _, item := range args.RoleIds {
		userRoles = append(userRoles, entity.SysUserRole{UserId: sysUser.UserId, RoleId: item})
	}
	if _, err := session.Insert(&userRoles); err != nil {
		return err
	}

	// 新增用户与岗位管理
	var userPosts []entity.SysUserPost
	for _, item := range args.PostIds {
		userPosts = append(userPosts, entity.SysUserPost{UserId: sysUser.UserId, PostId: item})
	}
	if _, err := session.Insert(&userPosts); err != nil {
		return err
	}

	return session.Commit()
}

// Edit 改
func (m *UserDao) Edit(args *entity.UserDto) error {
	session := pgCli.NewSession()
	defer session.Close()
	if err := session.Begin(); err != nil {
		return err
	}

	if len(args.RoleIds) > 0 {
		// 删除用户与角色关联
		if _, err := session.Where("user_id = ?", args.UserId).Unscoped().Delete(&entity.SysUserRole{}); err != nil {
			return err
		}
		// 新增用户与角色管理
		var userRoles []entity.SysUserRole
		for _, item := range args.RoleIds {
			userRoles = append(userRoles, entity.SysUserRole{UserId: args.UserId, RoleId: item})
		}
		if _, err := session.Insert(&userRoles); err != nil {
			return err
		}
	}

	if len(args.PostIds) > 0 {
		// 删除用户与岗位关联
		if _, err := session.Where("user_id = ?", args.UserId).Unscoped().Delete(&entity.SysUserPost{}); err != nil {
			return err
		}
		// 新增用户与岗位管理
		var userPosts []entity.SysUserPost
		for _, item := range args.PostIds {
			userPosts = append(userPosts, entity.SysUserPost{UserId: args.UserId, PostId: item})
		}
		if _, err := session.Insert(&userPosts); err != nil {
			return err
		}
	}

	if _, err := pgCli.ID(args.UserId).Update(&entity.SysUser{
		Username: args.Username,
		Nickname: args.Nickname,
		Phone:    args.Phone,
		Email:    args.Email,
		Status:   args.Status,
		BaseStruct: dom.BaseStruct{
			UpdatedBy: args.UpdatedBy,
			Remark:    args.Remark,
		},
	}); err != nil {
		return err
	}

	return session.Commit()
}

// Del 删
func (m *UserDao) Del(ids string) (int64, error) {
	return pgCli.In("user_id", strings.Split(ids, `,`)).Delete(&entity.SysUser{})
}

// EditByIpAndTime 更新IP和登陆时间
func (m *UserDao) EditByIpAndTime(userId int64, ip string, time time.Time) error {
	_, err := pgCli.Table(&entity.SysUser{}).ID(userId).NoAutoTime().Update(
		map[string]interface{}{
			"login_ip":        ip,
			"last_login_time": time,
		})
	return err
}

// EditByAvatar 更新用户头像路径
func (m *UserDao) EditByAvatar(userId int64, url string) error {
	_, err := pgCli.Table(&entity.SysUser{}).ID(userId).Update(
		&entity.SysUser{
			Avatar: url,
		})
	return err
}

// ChangeStatus 改变状态
func (m *UserDao) ChangeStatus(userId int64, status string, updateBy string) (int64, error) {
	return pgCli.ID(userId).Update(&entity.SysUser{
		Status: status,
		BaseStruct: dom.BaseStruct{
			UpdatedBy: updateBy,
		},
	})
}

// UpdatePwd 更新密码
func (m *UserDao) UpdatePwd(userId int64, password string, updateBy string) (int64, error) {
	password, err := utils.NewCryptUtils().EnCrypt(password)
	if err != nil {
		return 0, err
	}
	return pgCli.ID(userId).Update(&entity.SysUser{
		Password: password,
		BaseStruct: dom.BaseStruct{
			UpdatedBy: updateBy,
		},
	})
}
